To further this, I've prepared this short document that describes how
to set up your BIND 8.x server in a chroot() environment under RedHat
Linux (but should apply to others as well). This document is largely
inspired by my friend Adam Shostack
and his paper on the
identical subject matter (which covers Solaris). Please read his paper
(and check out his entire page which contains good reading) after you've
been here.
NOTE: This is a living document and I expect changes
and small errors to be discovered over time. My DNS server is very
small and handles a limited number of zones and traffic. It is quite possible
that the information I supply here does not work for larger sites. If this
is your case please write me and tell me what is broken so I can change
it here! Your input will be given full credit and will help everyone
who wishes to contain the beast we call BIND.
Linux NOTE: Although I do all my development on RedHat
Linux, my WWW/SMTP/DNS server is in fact OpenBSD.
This document was originally written for OpenBSD usage, but was modified
to describe the procedure under Linux (which is only slightly different).
Because of this though, I openly admit that I have very little experience
running BIND under Linux in a chroot() environment. While I believe the
information in this area to be accurate it may in fact vary somewhat from
version to version of Linux. If this is the case then please write me and
tell me! I would like to make this document as accurate as possible and
this can only be done with your help.
Install the software per the directions included with the package.
Go to Obtuse Systems's FTP
site where you need to download their free program called: holelogd
(and some other neat utilities). This program allows you to create a /dev/log
socket under a chroot environment so syslog will work from named once it
has been contained. OpenBSD's syslogd already has a feature to do this
built in ("syslogd -a /chroot/dev/log"), but Linux does not (however it
should). This program will emulate this feature in OpenBSD.
Install holelogd per the instructions (usually in /usr/local/sbin).
Change the line:
'CDEBUG= -O2 -g'
To:
'CDEBUG= -O2 -static'
Go to the top of the BIND source directory and do a "make clean" followed by a "make". Go onto the next step where you will copy the files to the chroot() directory.
For the uninitiated, a statically linked program is one that does not
perform dynamic loading of libraries. For a chroot() environment it means
that the executable will be "self-contained" and will not cause an error
if you are missing a library file. While it is not necessary to have statically
linked files in the chroot() environment, it often makes setup easier.
I prefer to have all network daemons statically linked for this reason.
Under this directory you will need to create the following directory structure:
/dev
/etc
/namedb
/usr
/sbin
/var
/run
Under each directory you will need to copy the following files and/or perform the following commands:
/
None
/etc
copy named.conf from /etc
copy localtime from /etc (so named logs correct
timezone in syslog)
create /etc/group file with named GID as the
only entry (Thanks Bernhard Weisshuhn <bkw@weisshuhn.de>)
/etc/namedb
copy all zone databases and files from /etc/namedb
/dev
mknod ./null c 1 3; chmod 666 null
(For other Linux variants, look at /dev/MAKEDEV to get the mknod command)
/usr/sbin
copy statically
linked named and named-xfer binary from the BIND src/bin/named
and src/bin/named-xfer directories
/var/run
None
Additionally, Bernhard Weisshuhn <bkw@weisshuhn.de>, writes that
if you have custom logging directories specified that you need to be sure
to make these as well (/var/log). Although named won't crash, it will complain.
You should now go to the /chroot/named/var/run directory and make it writable by named so the named.pid file can be written to upon startup. This is used by the ndc command to control named's operation.
At this point you may want to go into your chroot named area and chown -R named.named on the /etc/namedb directory. This allows named to dump cache and statistical information if you send it the proper signal (kill -INT <PID>). This change should not significantly effect the security of your chroot() setup. Leaving it owned as root won't allow named to write out this information (remember named now runs under a new UID and no longer root), but still allows named to function. A second option is to change the permissions to allow writing to this directory, but leaving it owned by root. This could also work but you need to be careful with doing so to ensure normal users can't modify your named records!
IMPORTANT: ** DO NOT USE AN EXISTING UID/GID to
run named under (i.e. "nobody"). It is always a bad idea to use
an existing UID/GID under a chroot environment as it can impact the protection
offered by the service. Make a separate UID/GID for every daemon
you run under chroot() as a matter of practice.
1) Put in a line before executing named to start up holelogd. holelogd needs to be told where to put the remote socket, this should be your chroot named dev directory made above. It should look something like this:
# Start daemons.
echo -n "Staring holelogd:
"
daemon /usr/local/sbin/holelogd
/chroot/named/dev/log
echo
echo -n "Starting named:
"
daemon named
echo
touch /var/lock/subsys/named
;;
2) You will also need to change the startup flags for BIND. Version
8.x has a feature where you can change the user and group ID after binding.
This is where you specify your UID/GID you assigned to BIND above:
# Start daemons.
echo -n "Staring holelogd:
"
daemon /usr/local/sbin/holelogd
/chroot/named/dev/log
echo
echo -n "Starting named:
"
daemon /chroot/named/usr/sbin/named
-u named -g named -t /chroot/named
echo
touch /var/lock/subsys/named
;;
3) named ships with a script called "ndc" which is used to control
named operations. You will need to edit this file and change the location
of the variable PIDFILE from /var/run/named.pid to /chroot/named/var/run/named.pid.
/usr/local/sbin/holelogd /chroot/named/dev/log
Go into this directory and ls -al. You should see (the date is insignificant):
srw-rw-rw- 1 root wheel 0 Jan 01 12:00 log
The "s" bit is set to indicate that the file is a socket. This is how named will write to syslog from within the chroot() jail.
Now type:
/chroot/named/usr/sbin/named -u named -g named -t /chroot/named
If all goes well named will start and your logs will indicate that named is "Ready to answer queries."
Perform other DNS tests as appropriate to ensure operation, then reboot your system and verify the setup. BIND should have started and reported it chroot()ed to to directory and changed UID/GID. You can use a program such as lsof to list out the owner of all network sockets on the host. The owner should be your named UID/GID.
When everything is working you should either rename /etc/namedb
to something like /etc/namedb.orig and chmod 000 /usr/sbin/named
to ensure that the old version doesn't get run by mistake. Reboot your
system and assuming everything is correct your named will now be chroot()ed.
Steinar Haug <sthaug@nethelp.no> - Comments concerning blocking of TCP to port 53.
Bernhard Weisshuhn <bkw@weisshuhn.de> - Comments pertaining to Linux install (typos, adding /etc/group entry).
Marc Heuse <Marc.Heuse@mail.deuba.com> - Comments pertaining to logging and renaming of old binaries and directories.
Jan Gruber <jgr@tpnet.de> - Comments pertaining to permissions on /chroot/named/var/run and changes to the ndc control script.
Adam Shostack's Home Page - Good reading on various items.
Internet Software Consortium - Suppliers of BIND, INN, and other software.